#!/bin/sh

log="/userdata/system/logs/display.log"

f_usage() {
    echo "${0} listModes" >&2
    echo "${0} setMode <MODE>" >&2
    echo "${0} currentMode" >&2
    echo "${0} currentResolution" >&2
    echo "${0} listOutputs" >&2
    echo "${0} currentOutput" >&2
    echo "${0} setOutput" >&2
    echo "${0} minTomaxResolution" >&2
    echo "${0} minTomaxResolution-secure" >&2
    echo "${0} setRotation (0|1|2|3)" >&2
    echo "${0} getRotation" >&2
    echo "${0} getDisplayMode" >&2
    echo "${0} getDisplayComp" >&2
}

f_minTomaxResolution() {
    # minimize resolution because of 4K tv
    MWIDTH=$(echo "$1"x | tr -d [[:blank:]] | cut -dx -f1) # the final added x is for compatibility with v29
    MHEIGHT=$(echo "$1"x | tr -d [[:blank:]] | cut -dx -f2)

    if [ -n "$MWIDTH" ] && [ -n "$MHEIGHT" ] && [ "$MWIDTH" != 0 ] && [ "$MHEIGHT" != 0 ]; then
        MAXWIDTH="$MWIDTH"
        MAXHEIGHT="$MHEIGHT"
    else
        MAXWIDTH=1920
        MAXHEIGHT=1080
    fi

    CURRENT_RESOLUTION=$(swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").current_mode | "\(.width)x\(.height)"')
    CURRENTWIDTH=$(echo "${CURRENT_RESOLUTION}" | cut -d x -f 1)
    CURRENTHEIGHT=$(echo "${CURRENT_RESOLUTION}" | cut -d x -f 2)

    if [ "${CURRENTWIDTH}" -le "${MAXWIDTH}" ] && [ "${CURRENTHEIGHT}" -le "${MAXHEIGHT}" ]; then
        exit 0
    fi

    # Select a new one
    swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").modes[] | "\(.width)x\(.height)"' |
    while read -r SUGGRESOLUTIONRATE SUGGMODE; do
        SUGGRESOLUTION=$(echo "${SUGGRESOLUTIONRATE}" | cut -d . -f 1)
        SUGGWIDTH=$(echo "${SUGGRESOLUTION}" | cut -d x -f 1)
        SUGGHEIGHT=$(echo "${SUGGRESOLUTION}" | cut -d x -f 2)

        if [ "${SUGGWIDTH}" -le "${MAXWIDTH}" ] && [ "${SUGGHEIGHT}" -le "${MAXHEIGHT}" ]; then
            swaymsg output "${PSCREEN}" mode "${SUGGRESOLUTION}"
            exit 0
        fi
    done
}

if [ $# -eq 0 ]; then
    f_usage
    exit 1
fi

PSCREEN=
if [ "$1" = "--screen" ]; then
    shift
    PSCREEN=$1
    shift
fi

# Set default screen
if [ -z "${PSCREEN}" ]; then
    PSCREEN=$(swaymsg -t get_outputs | jq -r '.[].name' | head -1)
fi

ACTION=$1
shift

case "${ACTION}" in
    "listModes")
        echo "max-1920x1080:maximum 1920x1080"
        echo "max-640x480:maximum 640x480"
        swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").modes[] | "\(.width)x\(.height).\(.refresh):\(.width)x\(.height) \(.refresh / 1000) Hz"' | uniq
        ;;

    "setMode")
        MODE=$1
        if echo "${MODE}" | grep -qE 'max-'; then # special max-widthxheight
            SPMODE=$(echo "${MODE}" | sed -e s+"^max-"++)
            f_minTomaxResolution "${SPMODE}"
        else # normal mode
            # let the old format widthxheight and the new one widthxheight.hz
            if echo "${MODE}" | grep "\."; then
                PARTRES=$(echo "${MODE}" | cut -d'.' -f1)
                PARTHZ=$(echo "${MODE}" | cut -d'.' -f2- | awk '{ printf "%.3f", $0 / 1000 }')
                swaymsg output "${PSCREEN}" mode "${PARTRES}"@"${PARTHZ}"Hz
            else
                swaymsg output "${PSCREEN}" mode "${MODE}"
            fi
        fi
        ;;

    "currentMode")
        swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").current_mode | "\(.width)x\(.height).\(.refresh)"'
        ;;

    "currentResolution")
        # To get the current resolution in case of rotation, change width and height
        # Don't exchange for mode while mode is more a technical value
        RAW_RESOLUTION=$(swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").current_mode | "\(.width)x\(.height)"')
        RAW_ROTATION=$(swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").transform')
        if [ "${RAW_ROTATION}" = "90" ] || [ "${RAW_ROTATION}" = "270" ]; then
            echo "${RAW_RESOLUTION}" | sed -e s+'^\([0-9]*\)x\([0-9]*\)$'+'\2x\1'+
        else
            echo "${RAW_RESOLUTION}"
        fi
        ;;

    "listOutputs")
        swaymsg -t get_outputs | jq -r '.[].name'
        ;;

    "currentOutput")
        swaymsg -t get_outputs | jq -r '.[] | select(.name == "'${PSCREEN}'").name'
        ;;

    "setOutput")
        # Not yet able to switch screen
	    swaymsg assign [app_id="^batocera-backglass-window$"] 2

        MODE1=$1
        MODE2=$2
        MODE3=$3
        if swaymsg -t get_outputs | jq -r '.[].name' | grep -qE "^${MODE1}$"; then
            # Disable all other outputs
            swaymsg -t get_outputs | jq -r '.[].name' | grep -vE "^${MODE1}$|^${MODE2}$|^${MODE3}$" |
            while read -r OUTP; do
                echo "set ${OUTP} off" >&2
                swaymsg output "${OUTP}" disable
            done

            echo "set ${MODE1} as primary" >&2
            swaymsg output "${MODE1}" enable
            PREVIOUS_SCREEN="${MODE1}"

            # Screen 2
            if [ -n "${MODE2}" ] && swaymsg -t get_outputs | jq -r '.[].name' | grep -qE "^${MODE2}$"; then
                echo "set user output: ${MODE2} as right of ${PREVIOUS_SCREEN}" >&2
                swaymsg output "${MODE2}" enable
                PREVIOUS_SCREEN="${MODE2}"
            fi
        else
            # Disable all except the first one
            swaymsg -t get_outputs | jq -r '.[].name' | {
                read -r FIRSTOUTPUT
                while read -r OUTP; do
                    echo "set ${OUTP} off" >&2
                    swaymsg output "${OUTP}" disable
                done
                echo "set ${FIRSTOUTPUT} as primary" >&2
                swaymsg output "${FIRSTOUTPUT}" enable
            }
        fi
        ;;

    "minTomaxResolution" | "minTomaxResolution-secure")
        f_minTomaxResolution "$1"
        ;;

    "supportSystemRotation")
        exit 0
        ;;

    "supportSystemReflection")
        exit 1
        ;;

    "setRotation")
        ROTATE=$1
        RETRIES=5
        TOUCHSCREEN=""
        for i in $(seq 1 $RETRIES); do
            TOUCHSCREEN=$(swaymsg -t get_inputs | jq -r '.[] | select(.type | ascii_downcase == "touch") | .identifier')
            if [ -n "${TOUCHSCREEN}" ]; then
                echo "Touchscreen identifier is: ${TOUCHSCREEN}" >> $log
                break
            fi
            # If not found, wait for another second and try again
            sleep 1
        done

        case "${ROTATE}" in
            "1")
                echo "Rotate 90 degrees" >> $log
                swaymsg output "${PSCREEN}" transform 90
                if [ -n "${TOUCHSCREEN}" ]; then
                    swaymsg -t command "input \"${TOUCHSCREEN}\" map_to_output \"${PSCREEN}\""
                    echo "Mapped touchscreen to ${PSCREEN}" >> $log
                    swaymsg -t command "input \"${TOUCHSCREEN}\" calibration_matrix 0 -1 1 1 0 0"
                    echo "Touchscreen rotated 90 degrees" >> $log
                fi
            ;;
            "2")
                echo "Rotate 180 degrees" >> $log
                swaymsg output "${PSCREEN}" transform 180
                if [ -n "${TOUCHSCREEN}" ]; then
                    swaymsg -t command "input \"${TOUCHSCREEN}\" map_to_output \"${PSCREEN}\""
                    echo "Mapped touchscreen to ${PSCREEN}" >> $log
                    swaymsg -t command "input \"${TOUCHSCREEN}\" calibration_matrix -1 0 1 0 -1 1"
                    echo "Touchscreen rotated 180 degrees" >> $log
                fi
            ;;
            "3")
                echo "Rotate 270 degrees" >> $log
                swaymsg output "${PSCREEN}" transform 270
                if [ -n "${TOUCHSCREEN}" ]; then
                    swaymsg -t command "input \"${TOUCHSCREEN}\" map_to_output \"${PSCREEN}\""
                    echo "Mapped touchscreen to ${PSCREEN}" >> $log
                    # this touchscreen doesn't need a rotated matrix
                    if [ "${TOUCHSCREEN}" = "0:0:generic_ft5x06_(a0)" ]; then
                        echo "Applying normal matrix for ${TOUCHSCREEN} at 270 degrees" >> $log
                        swaymsg -t command "input \"${TOUCHSCREEN}\" calibration_matrix 1 0 0 0 1 0"
                    else
                        swaymsg -t command "input \"${TOUCHSCREEN}\" calibration_matrix 0 1 0 -1 0 1"
                    fi
                    echo "Touchscreen rotated 270 degrees" >> $log
                fi
            ;;
            # In case of reboot of ES
            *)
                swaymsg output "${PSCREEN}" transform normal
                if [ -n "${TOUCHSCREEN}" ]; then
                    swaymsg -t command "input \"${TOUCHSCREEN}\" map_to_output \"${PSCREEN}\""
                    echo "Mapped touchscreen to ${PSCREEN}" >> $log
                    swaymsg -t command "input \"${TOUCHSCREEN}\" calibration_matrix 1 0 0 0 1 0"
                    echo "Touchscreen rotated 0 degrees" >> $log
                fi
            ;;
        esac
        ;;
    
    "getRotation")
        swaymsg -t get_outputs | jq -r '.[] | select(.name == "'"${PSCREEN}"'") | .transform'
        ;;

    "mapTouchScreen")
        # Mapping touch screen
        TOUCHSCREEN=$(swaymsg -t get_inputs | jq -r '.[] | select(.name == "'${PSCREEN}'") | select(.type == "touch") | .identifier')
        if [ -n "${TOUCHSCREEN}" ]; then
            swaymsg input "${TOUCHSCREEN}" map_to_output "${PSCREEN}"
        fi
        ;;

    "getDisplayMode")
        echo "wayland"
        ;;
    
    "getDisplayComp")
        echo "sway"
        ;;

    *)
        f_usage
        echo "error: invalid command ${ACTION}" >&2
        exit 1
        ;;
esac

exit 0
